package com.ylr.basic.framework.controller.api;

import com.ylr.base.common.enums.AesEnum;
import com.ylr.base.common.tool.Result;
import com.ylr.basic.common.enums.BasicResultEnum;
import com.ylr.basic.common.vo.AesVo;
import com.ylr.basic.framework.feign.YbAesBaseClient;
import com.ylr.basic.framework.service.AesService;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.util.Map;
import java.util.Objects;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-04-21 14:36:45
 * className: AesWebController AES加解密web请求接口类
 * version: 1.0
 * description:
 */
@Validated
@RestController
@RequestMapping("/api/aes")
@AllArgsConstructor
public class AesApiController implements YbAesBaseClient {

    private static final Logger log = LoggerFactory.getLogger(AesApiController.class);

    private final AesService aesService;

    /**
     * 明文加密接口
     * @param aesVo 参数对象
     * @return 密文
     */
    @PostMapping("/encrypt")
    public Result<String> encrypt(@Validated @RequestBody AesVo aesVo) {
        log.info("api => 开始明文AES加密操作。{}", aesVo);

        AesEnum aesEnum = AesEnum.getAesTypeEnum(aesVo.getType());
        if (Objects.isNull(aesEnum)) {
            log.info("AES操作类型值错误");
            return Result.getResult(BasicResultEnum.AES_TYPE_FAIL);
        }

        String cipherText;
        if (AesEnum.HEX == aesEnum) {
            cipherText = aesService.encryptToHex(aesVo.getValue());
        } else {
            cipherText = aesService.encryptToBase64(aesVo.getValue());
        }

        log.info("api => 明文AES加密操作完成");
        return Result.success(cipherText);
    }

    /**
     * 明文加密接口
     * 生成十六进制密文
     * @param plainText 明文
     * @return 密文
     */
    @PostMapping("/encrypt/hex")
    public Result<String> encryptToHex(@NotBlank(message = "明文不能为空") @RequestParam("plainText") String plainText) {
        log.info("api => 开始明文AES加密操作，生成十六进制密文。 plainText={}", plainText);

        String cipherText = aesService.encryptToHex(plainText);

        log.info("api => 明文AES加密操作完成");
        return Result.success(cipherText);
    }

    /**
     * 批量明文加密接口
     * 生成十六进制密文
     * @param paramMap 参数映射
     * @return 结果映射
     */
    @PostMapping("/batch/encrypt/hex")
    public Result<Map<?, String>> batchEncryptToHex(@Size(min = 1, message = "参数映射不能为空") @RequestBody Map<?, String> paramMap) {
        log.info("api => 开始批量明文AES加密操作，生成十六进制密文。 paramMap={}", paramMap);

        Map<?, String> resultMap = aesService.batchEncryptToHex(paramMap);

        log.info("api => 批量明文AES加密操作完成");
        return Result.success(resultMap);
    }

    /**
     * AES密文解密接口
     * @param cipherText 密文
     * @return 明文
     */
    @PostMapping("/decode/hex")
    public Result<String> decodeHex(@NotBlank(message = "密文不能为空") @RequestParam("cipherText") String cipherText) {
        log.info("api => 开始AES密文（十六进制）解密操作。 cipherText={}", cipherText);

        String plainText = aesService.decodeHex(cipherText);

        log.info("api => AES密文（十六进制）解密操作完成");
        return Result.success(plainText);
    }

    /**
     * AES密文半解密接口
     * @param cipherText 密文
     * @param start      脱敏开始下标
     * @param end        脱敏结束下标
     * @return 明文
     */
    @PostMapping("/sub/decode/hex")
    public Result<String> subDecodeHex(@NotBlank(message = "密文不能为空") @RequestParam("cipherText") String cipherText,
                                       @RequestParam(value = "start", required = false) Integer start,
                                       @RequestParam(value = "end", required = false) Integer end) {
        log.info("api => 开始AES密文（十六进制）半解密操作。 cipherText={} start={} end={}", cipherText, start, end);
        if (Objects.isNull(start)) {
            start = 3;
        }
        if (Objects.isNull(end)) {
            end = 4;
        }
        String plainText = aesService.subDecodeHex(cipherText, start, end);

        log.info("api => AES密文（十六进制）半解密操作完成");
        return Result.success(plainText);
    }

    /**
     * 明文加密接口
     * 生成Base64密文
     * @param plainText 明文
     * @return 密文
     */
    @PostMapping("/encrypt/base64")
    public Result<String> encryptToBase64(@NotBlank(message = "明文不能为空") @RequestParam("plainText") String plainText) {
        log.info("api => 开始明文AES加密操作，生成Base64密文。plainText={}", plainText);

        String cipherText = aesService.encryptToBase64(plainText);

        log.info("api => 明文AES加密操作完成");
        return Result.success(cipherText);
    }

    /**
     * AES密文解密接口
     * @param cipherText 密文
     * @return 明文
     */
    @PostMapping("/decode/base64")
    public Result<String> decodeBase64(@NotBlank(message = "密文不能为空") @RequestParam("cipherText") String cipherText) {
        log.info("api => 开始AES密文（Base64）解密操作。cipherText={}", cipherText);

        String plainText = aesService.decodeBase64(cipherText);

        log.info("api => AES密文（Base64）解密操作完成");
        return Result.success(plainText);
    }

    /**
     * AES密文半解密接口
     * @param cipherText 密文
     * @return 明文
     */
    @PostMapping("/sub/decode/base64")
    public Result<String> subDecodeBase64(@NotBlank(message = "密文不能为空") @RequestParam("cipherText") String cipherText,
                                          @RequestParam(value = "start", required = false) Integer start,
                                          @RequestParam(value = "end", required = false) Integer end) {
        log.info("api => 开始AES密文（Base64）半解密操作。cipherText={} start={} end={}", cipherText, start, end);
        if (Objects.isNull(start)) {
            start = 3;
        }
        if (Objects.isNull(end)) {
            end = 4;
        }

        String plainText = aesService.subDecodeBase64(cipherText, start, end);

        log.info("api => AES密文（Base64）半解密操作完成");
        return Result.success(plainText);
    }

    /**
     * 密文解密接口
     * @param aesVo 参数对象
     * @return 明文
     */
    @PostMapping("/decode")
    public Result<String> decode(@Validated @RequestBody AesVo aesVo) {
        log.info("api => 开始密文解密操作。{}", aesVo);

        int count = 0;
        Integer start = aesVo.getStart();
        if (Objects.isNull(start)) {
            start = 3;
            count += 1;
        }
        Integer end = aesVo.getEnd();
        if (Objects.isNull(end)) {
            end = 4;
            count += 1;
        }

        AesEnum aesEnum = AesEnum.getAesTypeEnum(aesVo.getType());
        if (Objects.isNull(aesEnum)) {
            log.info("AES操作类型值错误");
            return Result.getResult(BasicResultEnum.AES_TYPE_FAIL);
        }

        String plainText;
        if (count == 0) {
            if (AesEnum.HEX == aesEnum) {
                plainText = aesService.subDecodeHex(aesVo.getValue(), start, end);
            } else {
                plainText = aesService.subDecodeBase64(aesVo.getValue(), start, end);
            }
        } else {
            if (AesEnum.HEX == aesEnum) {
                plainText = aesService.decodeHex(aesVo.getValue());
            } else {
                plainText = aesService.decodeBase64(aesVo.getValue());
            }
        }
        log.info("api => 密文解密操作结束");
        return Result.success(plainText);
    }

    /**
     * 批量密文解密接口
     * @param type     密文类型[1-hex 2-base64]
     * @param paramMap 参数映射集合
     * @return 明文映射集合
     */
    @PostMapping("/batch/decode")
    public Result<Map<?, String>> batchDecode(@RequestParam("type") Integer type,
                                              @Size(min = 1, message = "参数映射不能为空") @RequestBody Map<?, String> paramMap) {
        log.info("api => 开始批量密文解密操作。type={} paramMap={}", type, paramMap);

        AesEnum aesEnum = AesEnum.getAesTypeEnum(type);
        if (Objects.isNull(aesEnum)) {
            log.info("AES操作类型值错误");
            return Result.getResult(BasicResultEnum.AES_TYPE_FAIL);
        }

        Map<?, String> result;
        if (AesEnum.HEX == aesEnum) {
            result = aesService.batchDecodeHex(paramMap);
        } else {
            result = aesService.batchDecodeBase64(paramMap);
        }

        log.info("api => 批量密文解密操作结束");
        return Result.success(result);
    }

}
